2023-03-01 LlamaIndexのコードを読む
LlamaIndexのコードを読むnishio.icon
LlamaIndexのNodeの単位をどうやって制御するのかnishio.icon
これは単にファイルを読んでDocumentを返してるだけ
これは文字列のリストを個別にDocumentにしてる
トークン数を数えるのにはこれを使ってる
tiktoken.get_encoding("gpt2")
GPT2から変わってないのか
Yes
GPTIndexを作る際に勝手にドキュメントを結合してしまう?
DocumentStoreの中身が1個になっちゃう?
ノードが分かれてるからちゃんとそのノードだけ読むようだ
断片にインデックスをつけるのができるようになった
クオリアさんの過去発言データを整備すれば...
def get_queued_text_embeddings(self) -> Tuple[List[str], List[List[float]]]:
OpenAIEmbedding#get_embedding
この辺が最終的に呼ばれるのだろう
GPTVectorStoreIndex
BaseGPTIndex
ここでOpenAIEmbedding
default: "text-embedding-ada-002"
そうなのか〜
- OpenAIEmbeddingMode.SIMILARITY_MODE
- OpenAIEmbeddingMode.TEXT_SEARCH_MODE
TEXT_SEARCH_MODEがdefault
self.build_index_from_documents(documents)が呼ばれる
そこの先は_build_index_from_documentsが@abstractmethod
で子クラスに戻る
self._use_async default: Falseなので
code:py
for d in documents:
self._add_document_to_index(index_struct, d)
self._get_node_embedding_results(...)
code:py
def _get_node_embedding_results(
self, nodes: ListNode, existing_node_ids: Set, doc_id: str 各nodeのtextをqueueに入れてから
result_ids, result_embeddings = self._embed_model.get_queued_text_embeddings()
ここでOpenAIEmbeddingに処理が移る
おっと違ったBaseEmbeddingのget_queued_text_embeddingsだ
これがembeddings = self._get_text_embeddings(cur_batch_texts)する
で、もちろん_get_text_embeddingsがOpenAIEmbeddingでオーバーライドされてるわけだ
だいぶ著者の気持ちが読めるようになってきたw
OpenAIEmbedding#_get_text_embeddings
embeddings = get_embeddings(texts, engine=engine)
get_embeddingsの中でOpenAIを呼んでる
data = openai.Embedding.create(input=list_of_text, engine=engine).data
index.query
BaseGPTIndex#query
return query_runner.query(query_str, self._index_struct)
/gpt_index/indices/query/query_runner.py
return query_obj.query(query_bundle)
/gpt_index/indices/query/base.py
BaseGPTIndexQuery
def _query(self, query_bundle: QueryBundle) -> Response:
tuples = self.get_nodes_and_similarities_for_response(query_bundle)
ここで類似度に基づく検索をしている
[(Node(text='56: Have Presence of Mind.\n...', doc_id='a8e898fd-...', embedding=None, extra_info=None, index=0, child_indices=set(), ref_doc_id='a51e3fc7-...', node_info={'start': 0, 'end': 602}), 0.800589425093737)]
text, response = self._get_text_from_node(query_bundle, node)
なぜ_get_text_from_nodeがresponseを返す?
recursiveのとき、リクエストを発行することがあるから
今回の場合はしないのでNoneが返る
response_str = self._give_response_for_nodes(query_bundle.query_str)
response = self.response_builder.get_response(...)
ResponseBuilder
give_response_single
2023-03-05nishio.icon
GPTVectorStoreIndexQueryの_get_nodes_for_responseでquery_result = self._vector_store.query(query_embedding, self._similarity_top_k)してる
SimpleVectorStore#queryがユーティリティ関数get_top_k_embeddingsを呼び出してる
この中で、全部類似度を計算して、ソートしてK個取ったものを返してる
つまり「ベクトルサーチの結果をトークン上限Xで返させる」オプションはない
2023-03-07
デフォルトはコサイン類似度
def similarity(
OpenAI embeddings are normalized to length 1, which means that: doc 区別する意味ないな
LlamaIndexもFAISSを使うことができそう
def load_from_disk(
デフォルトはJSON